﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.NewtonsoftJson;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Converters;
using System.Linq;
using System.Reflection;

namespace Shared.NewtonsoftJsonHelper
{
    public static class NewtonsoftJsonExtensions
    {
        /// <summary>
        /// 使用 Newtonsoft 替换 系统默认的 json格式化组件
        /// 格式化日期时间格式;  yyyy-MM-dd HH:mm:ss
        /// 
        /// 如果Post上来的数据日期时间格式是: yyyy-MM-dd 
        /// 需要额外设置字段属性的Json日期格式模式 
        /// [JsonConverter(typeof(ShortDateFormatConvert))]
        /// 
        // </summary>
        /// <param name="service"></param>
        /// <returns></returns>
        public static IMvcBuilder UseNewtonsoftJson(this IMvcBuilder mvcBuilder)
        {
            return mvcBuilder.AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.Formatting = Formatting.Indented;
                options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver();
                options.SerializerSettings.Converters.Add(new IsoDateTimeConverter()
                {
                    DateTimeFormat = "yyyy-MM-dd HH:mm:ss"
                });
                options.SerializerSettings.Converters.Add(new DateConverter());
            });
        }

        #region 将 null 转换成 ""

        /// <summary>
        /// json属性值转为日期
        /// </summary>
        public class DateConverter : IsoDateTimeConverter
        {
            /// <summary>
            /// 类构造
            /// </summary>
            public DateConverter()
            {
                base.DateTimeFormat = "yyyy-MM-dd";
            }
        }
        /// <summary>
        /// 将 null 转换成 ""
        /// </summary>
        private class NullToEmptyStringResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
        {
            protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
            {
                return type.GetProperties()
                        .Select(p => {
                            var jp = base.CreateProperty(p, memberSerialization);
                            jp.ValueProvider = new NullToEmptyStringValueProvider(p);
                            return jp;
                        }).ToList();
            }
        }
        /// <summary>
        /// 将 null 转换成 ""
        /// </summary>
        private class NullToEmptyStringValueProvider : IValueProvider
        {
            PropertyInfo _MemberInfo;
            public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
            {
                _MemberInfo = memberInfo;
            }
            public object GetValue(object target)
            {
                object result = _MemberInfo.GetValue(target);
                if (_MemberInfo.PropertyType == typeof(string) && result == null)
                {
                    result = "";
                }
                return result;
            }

            public void SetValue(object target, object value)
            {
                _MemberInfo.SetValue(target, value);
            }
        }
        #endregion
    }
}
